import { cloneDeep, omit } from 'lodash-es';
import type { Router, RouteRecordNormalized, RouteRecordRaw } from 'vue-router';
import { createRouter, createWebHashHistory } from 'vue-router';

import { DEFAULT_LAYOUT } from '@/router/routes/base';
import type { AppRouteRecordRaw } from '@/router/routes/types';
import { useAppStore } from '@/store';
import { isUrl } from '@/utils/is';
const views = import.meta.glob('../views/**/*.vue');

export const pathResolve = (parentPath: string, path: string) => {
  if (isUrl(path)) return path;
  const childPath = path.startsWith('/') || !path ? path : `/${path}`;
  return `${parentPath}${childPath}`.replace(/\/\//g, '/');
};

export const addServerRoutes = (router: Router) => {
  const appStore = useAppStore();
  const arr: any = [];
  appStore.appAsyncMenus.forEach((value) => {
    arr.push({
      name: value.name,
      redirect: value.redirect,
      path: value.path,
      component: DEFAULT_LAYOUT,
      children: resolveRouteChild(value),
      meta: {
        title: value.meta?.title,
        icon: value.meta?.icon,
        order: value.meta?.order,
        hidden: value.meta?.hidden,
        activeMenu: value.meta?.activeMenu,
      },
    });
  });
  const addRoutes = flatMultiLevelRoutes(arr);
  addRoutes.forEach((value: any) => {
    router.addRoute(value);
  });
};

const resolveRouteChild = (value: AppRouteRecordRaw) => {
  const child: RouteRecordRaw[] = [];
  if (value.children && value.children.length) {
    value.children.forEach((val) => {
      let component;
      if (val.component) {
        const comModule =
          views[`../${val.component}.vue`] || views[`../${val.component}.tsx`];
        const componentStr = val.component as string;
        if (!comModule && !componentStr.includes('#')) {
          // eslint-disable-next-line no-console
          console.error(
            `未找到${val.component}.vue文件或${val.component}.tsx文件，请创建!`
          );
        } else {
          // 动态加载路由文件，可根据实际情况进行自定义逻辑
          // eslint-disable-next-line no-lonely-if
          if (componentStr === '#') {
            component = DEFAULT_LAYOUT;
          } else if (componentStr === '##') {
            component = getParentLayout();
          } else {
            component = comModule;
          }
        }
      }
      child.push({
        name: val.name,
        path: val.path,
        component,
        children: resolveRouteChild(val),
        meta: {
          title: val.meta?.title,
          requiresAuth: val.meta?.requiresAuth as boolean,
          roles: val.meta?.roles,
          hidden: val.meta?.hidden,
          activeMenu: val.meta?.activeMenu,
        },
      });
    });
  }
  return child;
};

/**
 * 扁平化多级路由
 */
const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => {
  const modules: AppRouteRecordRaw[] = cloneDeep(routes);
  for (let index = 0; index < modules.length; index += 1) {
    const route = modules[index];
    if (isMultipleRoute(route)) {
      promoteRouteLevel(route);
    }
  }
  return modules;
};

/**
 * 判断层级是否大于2级
 */
const isMultipleRoute = (route: AppRouteRecordRaw) => {
  if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
    return false;
  }
  let result = false;
  const { children } = route;
  for (let index = 0; index < children.length; index += 1) {
    const child = children[index];
    if (child.children?.length) {
      result = true;
      break;
    }
  }
  return result;
};

/**
 * 第一步：将层级大于2级的路由处理成2级路由（大于第2级的路提升到第2级）
 * 第二部：将第2级路由的children属性删除
 */
const promoteRouteLevel = (route: AppRouteRecordRaw) => {
  let tempRouter: Router | null = createRouter({
    routes: [route as RouteRecordRaw],
    history: createWebHashHistory(),
  });

  const routes = tempRouter.getRoutes();
  addToChildren(routes, route.children || [], route);
  tempRouter = null;

  route.children = route.children?.map((item) => omit(item, 'children'));
};

const addToChildren = (
  routes: RouteRecordNormalized[],
  children: AppRouteRecordRaw[],
  routeModule: AppRouteRecordRaw
) => {
  for (let index = 0; index < children.length; index += 1) {
    const child = children[index];
    const route = routes.find((item) => item.name === child.name);
    if (route) {
      routeModule.children = routeModule.children || [];
      if (!routeModule.children.find((item) => item.name === route.name)) {
        routeModule.children?.push(route as unknown as AppRouteRecordRaw);
      }
      if (child.children?.length) {
        addToChildren(routes, child.children, routeModule);
      }
    }
  }
};

const getParentLayout = () => {
  return () =>
    new Promise((resolve) => {
      resolve({
        name: 'ParentLayout',
      });
    });
};
